# 引入必要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc, precision_recall_curve, average_precision_score
from keras.utils import to_categorical
from scipy import interp


def cal_auc(y_pred, y_true, columns=None, draw=False):
    """
    计算roc
    :param y_pred: 预测值 onehot编码
    :param y_true: 真实值 onehot编码
    :param columns: 每一列所代表的类别名称
    :return: 各roc值,为一字典，keys='macro','micro',0~len(y_pred[0])
    """
    # 计算每一类的ROC
    fpr = dict()
    tpr = dict()
    roc_auc = dict()
    for i in range(len(y_pred[0])):
        fpr[i], tpr[i], _ = roc_curve(y_true[:, i], y_pred[:, i])
        roc_auc[i] = auc(fpr[i], tpr[i])

    # micro-average ROC(方法二，转化为二分类法）
    fpr["micro"], tpr["micro"], _ = roc_curve(y_true.ravel(), y_pred.ravel())
    roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

    # macro-average ROC(方法一,平均法）
    all_fpr = np.unique(np.concatenate([fpr[i] for i in range(len(y_pred[0]))]))
    mean_tpr = np.zeros_like(all_fpr)
    for i in range(len(y_pred[0])):
        mean_tpr += interp(all_fpr, fpr[i], tpr[i])
    mean_tpr /= len(y_pred[0])
    fpr["macro"] = all_fpr
    tpr["macro"] = mean_tpr
    roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])

    if draw:
        # 画两类ROC曲线
        plt.figure()
        plt.plot(fpr["micro"], tpr["micro"],
                 label='micro-average ROC curve (area = {0:0.2f})'.format(roc_auc["micro"]), linestyle=':', linewidth=4)

        plt.plot(fpr["macro"], tpr["macro"],
                 label='macro-average ROC curve (area = {0:0.2f})'.format(roc_auc["macro"]), linestyle=':', linewidth=4)

        # 画所有分类别的ROC曲线
        if columns:
            for i in range(len(y_pred[0])):
                plt.plot(fpr[i], tpr[i], lw=2, label='ROC of {0} (area = {1:0.2f})'.format(columns[i], roc_auc[i]))
        else:
            for i in range(len(y_pred[0])):
                plt.plot(fpr[i], tpr[i], lw=2, label='ROC of {0} (area = {1:0.2f})'.format(i, roc_auc[i]))

        plt.plot([0, 1], [0, 1], 'k--', lw=2)
        plt.xlim([0.0, 1.0])
        plt.ylim([0.0, 1.05])
        plt.xlabel('False Positive Rate')
        plt.ylabel('True Positive Rate')
        plt.title('Some extension of Receiver operating characteristic to multi-class')
        plt.legend(loc="lower right")
        plt.show()
    return roc_auc


def cal_mAP(y_pred, y_true):
    """
    计算roc
    :param y_pred: 预测值 onehot编码
    :param y_true: 真实值 onehot编码
    :param columns: 每一列所代表的类别名称
    :return: 各ap值,为一字典，keys='macro','micro',0~len(y_pred[0])
    """
    # 计算每一类的ROC
    ap = dict()
    for index, value in enumerate(average_precision_score(y_true, y_pred, average=None)):
        ap[index] = value

    ap['micro'] = average_precision_score(y_true, y_pred, average='micro')
    ap['macro'] = average_precision_score(y_true, y_pred, average='macro')

    return ap


def cal_acc(y_pred, y_true):
    cnt = 0
    for i in range(len(y_pred)):
        if y_pred[i].argmax() == y_true[i].argmax():
            cnt += 1
    return cnt / len(y_pred)


def main(csv_path):
    data = pd.read_csv(csv_path)
    y_pred = data.iloc[:, 1:-1]
    y_pred = np.array(y_pred)

    y_true = data.loc[:, 'real']
    columns = list(data.iloc[:, 1:-1].columns)
    y_true = [columns.index(label.strip()) for label in y_true]
    y_true = to_categorical(y_true, num_classes=11)
    y_true = np.array(y_true)

    auc = cal_auc(y_pred, y_true, columns, draw=False)
    mAP = cal_mAP(y_pred, y_true)
    acc = cal_acc(y_pred, y_true)

    print('auc', auc['macro'])
    print('mAP', mAP['macro'])
    print('score', 0.7 * auc['macro'] + 0.3 * mAP['macro'])
    print('acc', acc)


if __name__ == '__main__':
    main('../submit/submit_model_weight_0.7239.hdf5.csv')
